/*
 * The Open Source Unix Installer
 *
 * The MIT License
 *
 * Copyright 2011-2012 Andrey Pudov.
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 */

/*
 * @author  Andrey Pudov    <andrey@andreypudov.com>
 * @version 0.00.00
 * @name    properties.c
 * @date:   Jan 18, 2012
 */

#include "properties.h"

/* private code declaration */
static Properties* _installer_properties_search(Properties *properties, 
                                                const char *key);
static Properties* _installer_properties_insert(Properties **properties, 
                                                const char *key, 
                                                const char *value, 
                                                Properties *parent);

/* public code definition */
Properties* installer_properties_new() {
    return NULL;
}

void installer_properties_delete(Properties *properties) {
    if (properties != NULL) {
        installer_properties_delete(properties->left);
        installer_properties_delete(properties->right);

        if (properties->key != NULL) {
            free(properties->key);
        }

        if (properties->value != NULL) {
            free(properties->value);
        }

        free(properties); 
    }
}

char* installer_properties_get(Properties *properties, const char *key) {
    Properties *properties_ptr;

    /* class instance and key value are can't be NULL */
    if ((properties == NULL) || (key == NULL)) {
        return NULL;
    }

    properties_ptr = _installer_properties_search(properties, key);

    return (properties_ptr != NULL) ? properties_ptr->value : NULL;
}

Properties* installer_properties_set(Properties **properties, const char *key, 
        const char *value) {

    /* class instance and key value are can't be NULL */
    if ((properties == NULL) || (key == NULL)) {
        return NULL;
    }

    return (_installer_properties_insert(properties, key, value, *properties));
}

/* private code definition */
Properties* _installer_properties_search(Properties *properties, 
                                         const char *key) {

    if (properties == NULL) {
        return NULL;
    }

    /* if properties->key is equal to key */
    if (strcmp(properties->key, key) == 0) {
        return properties;
    }

    /* if key is less than properties->key */
    if (strcmp(key, properties->key) < 0) {
        return (_installer_properties_search(properties->left, key));
    } else {
        return (_installer_properties_search(properties->right, key));
    }
}

Properties* _installer_properties_insert(Properties **properties, const char *key, 
                                  const char *value, Properties *parent) {

    /* temporary pointer */
    Properties *properties_ptr;

    if (*properties == NULL) {
        /* allocate memmory to the new node */
        properties_ptr = (Properties*) malloc(sizeof(Properties));
        if (properties_ptr == NULL) {
    	    return NULL;
        }

        /* key should be not NULL, value can be NULL */
        properties_ptr->key = strdup(key);
        properties_ptr->value = (value != NULL) ? strdup(value) : NULL;

        properties_ptr->left = NULL;
        properties_ptr->right = NULL;
        properties_ptr->parent = parent;

        /* the pointer  to the parent node */
        *properties = properties_ptr;

        return (*properties);
    }

    /* if key is less than (*properties)->key */
    int result = strcmp(key, (*properties)->key); 
    if (result < 0) {
        return (_installer_properties_insert(
                &((*properties)->left), key, value, *properties));
    } else if (result > 0) {
        return (_installer_properties_insert(
                &((*properties)->right), key, value, *properties));
    } else {
        free((*properties)->value);
        (*properties)->value = strdup(value);
        
        return (*properties);
    }
}
